package cl.whyem.testsutilityproject.recursion;

import com.google.common.primitives.Chars;
import java.util.Arrays;
import java.util.List;

public class Week1Scala {

    public static void main(String... args) {
        //pascal(0,2)=1, pascal(1,2)=2 and pascal(1,3)=3. and pascal(2,4)=6.
        //System.out.println("PASCAL CELDA (C,R) -> " + new Week1Scala().pascal(2, 4));

        //(if (zero? x) max (/ 1 x)) -> true
        //System.out.println("BALANCE -> " + new Week1Scala().balance(Chars.asList("(if (zero? x) max (/ 1 x))".toCharArray())));
        //countChange(4, [1,2]) -> 3 (1+1+1+1, 1+1+2, 2+2)
        System.out.println("VUELTO -> " + new Week1Scala().countChange(4, Arrays.asList(1, 2, 3)));
    }

    /**
     * Calcula valor de par (columna,fila) en triangulo pascal.
     */
    public Integer pascal(Integer c, Integer r) {
        if (c == 0 || c == r) {
            return 1;
        } else {
            return pascal(c - 1, r - 1) + pascal(c, r - 1);
        }
        //Pascal(fila, 0) = 1 para cualquier valor de fila
        //Pascal(fila, columna) = 1 si fila = columna
        //Pascal(fila, columna) = Pascal(fila-1,columna-1) + Pascal(fila-1, columna) en otro caso 
    }

    /**
     * Calcula si hay balance de parentesis, es decir para cada parentesis
     * abierto tiene que estar cerrado.
     */
    public Boolean balance(List<Character> chars) {
        return balance(chars, "");
    }

    private Boolean balance(List<Character> chars, String acc) {
        if (chars.isEmpty()) {
            return acc.isEmpty();
        } else if ("(".equals(chars.get(0).toString())) {
            return balance(chars.subList(1, chars.size()), "(" + acc);
        } else if (")".equals(chars.get(0).toString())) {
            return !acc.isEmpty() && balance(chars.subList(1, chars.size()), acc.substring(1));
        } else {
            return balance(chars.subList(1, chars.size()), acc);
        }
    }

    /**
     * Calcula el numero de posibles combinaciones de vuelto, con la lista de
     * monedas disponibles.
     */
    public Integer countChange(Integer money, List<Integer> coins) {
        if (money == 0) {
            return 1;
        } else if (money < 0 || coins.isEmpty()) {
            return 0;
        } else {
            return countChange(money, coins.subList(1, coins.size())) + countChange(money - coins.get(0), coins);
        }
    }

}
